/***************************************************************************************************
**
** This Code refrence from:
**
** Real-Time Hierarchical Profiling for Game Programming Gems 3
**
** by Greg Hjelstrom & Byon Garrabrant
**
***************************************************************************************************/


#include "ChaosProfileNode.hpp"

namespace Chaos
{


	/***********************************************************************************************
	 * INPUT:                                                                                      *
	 * name - pointer to a static string which is the name of this profile node                    *
	 * parent - parent pointer                                                                     *
	 *                                                                                             *
	 * WARNINGS:                                                                                   *
	 * The name is assumed to be a static pointer, only the pointer is stored and compared for     *
	 * efficiency reasons.                                                                         *
	 *=============================================================================================*/
	ChsProfileNode::ChsProfileNode( const TCHAR * name, ChsProfileNode * parent ) :
		m_szName( name ),
		m_nTotalCalls( 0 ),
		m_fTotalTime( 0 ),
		m_n64StartTime( 0 ),
		m_nRecursionCounter( 0 ),
		m_pParent( parent ),
		m_pChild( NULL ),
		m_pSibling( NULL )
	{
		Reset();
	}


	ChsProfileNode::~ChsProfileNode( void )
	{
		delete m_pChild;
		delete m_pSibling;
	}

	/***********************************************************************************************
	 * INPUT:                                                                                      *
	 * name - static string pointer to the name of the node we are searching for                   *
	 *                                                                                             *
	 * WARNINGS:                                                                                   *
	 * All profile names are assumed to be static strings so this function uses pointer compares   *
	 * to find the named node.                                                                     *
	 *=============================================================================================*/
	ChsProfileNode * ChsProfileNode::GetSubNode( const TCHAR * name )
	{
		// Try to find this sub node
		ChsProfileNode * child = m_pChild;
		while ( child )
		{
			if(child->m_szName == name )
			{
				return child;
			}
			child = child->m_pSibling;
		}

		// We didn't find it, so add it
		ChsProfileNode * node = new ChsProfileNode( name, this );
		node->m_pSibling = m_pChild;
		m_pChild = node;
		return node;
	}

	void	ChsProfileNode::Reset( void )
	{
		m_nLastTotalCalls = m_nTotalCalls;
		m_nTotalCalls = 0;
		m_fLastTotalTime = m_fTotalTime;
		m_fTotalTime = 0.0f;

		if ( m_pChild ) {
			m_pChild->Reset();
		}
		if ( m_pSibling ) {
			m_pSibling->Reset();
		}
	}

	void	ChsProfileNode::Call( void )
	{
		m_nTotalCalls++;
		if (m_nRecursionCounter++ == 0) {
			profileGetTicks(&m_n64StartTime);
		}
	}


	bool	ChsProfileNode::Return( void )
	{
		if ( --m_nRecursionCounter == 0 && m_nTotalCalls != 0 ) { 
			__int64 time;
			profileGetTicks(&time);
			time-=m_n64StartTime;
			m_fTotalTime += (float)time / profileGetTickRate();
		}
		return ( m_nRecursionCounter == 0 );
	}

}
